package com.lzh.hosp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzh.hosp.model.OrderInfo;
import com.lzh.hosp.model.Patient;
import com.lzh.hosp.model.Prescription;
import com.lzh.hosp.model.Schedule;
import com.lzh.hosp.service.OrderInfoService;
import com.lzh.hosp.service.PatientService;
import com.lzh.hosp.mapper.PatientMapper;
import com.lzh.hosp.service.PrescriptionService;
import com.lzh.hosp.service.ScheduleService;
import com.lzh.hosp.utils.CommonUtils;
import com.lzh.hosp.utils.RedisCache;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

/**
* @author 59399
* @description 针对表【patient(就诊人表)】的数据库操作Service实现
* @createDate 2023-03-21 21:23:10
*/
@Service
public class PatientServiceImpl extends ServiceImpl<PatientMapper, Patient>
    implements PatientService{

    @Autowired
    private ScheduleService scheduleService;

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private PrescriptionService prescriptionService;

    @Autowired
    private RedisCache redisCache;

    @Override
    public boolean add(Patient patient) {
        try {
            //判断有无重复的就诊卡
            QueryWrapper<Patient> wrapper = new QueryWrapper<>();
            wrapper.eq(!StringUtils.isEmpty(patient.getCertificatesType()),"certificates_type",patient.getCertificatesType());
            wrapper.eq(!StringUtils.isEmpty(patient.getCertificatesNo()),"certificates_no",patient.getCertificatesNo());
            Patient pat = baseMapper.selectOne(wrapper);
            if (!StringUtils.isEmpty(pat)){//说明重复了
                return false;
            }

            //生成8位的卡号
            String cardNo = UUID.randomUUID().toString().replace("-","").substring(0,8);
            patient.setCardNo(cardNo);

            //判断证件类型是否为身份证
            if (patient.getCertificatesType()==161){//如果是身份证，根据身份证得出性别年龄出生日期
                String idCard = patient.getCertificatesNo();
                //判断是否为合法身份证
                if (!CommonUtils.validateIdCard(idCard)){
                    return false;
                }
                int age = CommonUtils.getAgeForIdcard(idCard);
                Date birthday = CommonUtils.getBirthDayFromIdCard(idCard);
                int sex = CommonUtils.getSexFromIdCard(idCard);
                patient.setAge(age);
                patient.setSex(sex);
                patient.setBirthdate(birthday);
            }
            baseMapper.insert(patient);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public Patient findFirstByUserId(Long userId) {
        QueryWrapper<Patient> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        wrapper.orderByAsc("create_time");
        wrapper.last("limit 1");

        Patient patient = baseMapper.selectOne(wrapper);
        return patient;
    }

    @Override
    public String getPatientName(String cardNo) {
        QueryWrapper<Patient> wrapper = new QueryWrapper<>();
        wrapper.eq("card_no",cardNo);
        Patient patient = baseMapper.selectOne(wrapper);
        return patient.getName();
    }

    @Override
    public List<Patient> findByDocIdAndWorkDate(Long docId) {
        //根据医生编号和今天的日期日期查询出排班
        QueryWrapper<Schedule> wrapper = new QueryWrapper<>();
        wrapper.eq("doc_id",docId);
        wrapper.eq("work_date",new DateTime().toString("yyyy-MM-dd"));
        List<Schedule> scheduleList = scheduleService.list(wrapper);

        //根据docId找出redis中的队列
        List<Patient> patientListR =(List<Patient>) redisCache.getCacheObject("doctor:"+docId);

        //根据docId找出redis中的过号队列
        List<Patient> patientOvertimeList =(List<Patient>) redisCache.getCacheObject("doctor:"+docId+":overtime");

        //根据docId找出redis中的正在就诊病人id
        Patient patientVisit =(Patient) redisCache.getCacheObject("doctor:"+docId+":visit");

        //根据排班编号查询出病人
        List<Patient> patientList = new LinkedList<>();
        for (Schedule schedule : scheduleList) {
            //根据排班编号查出对应的订单
            QueryWrapper<OrderInfo> orderInfoWrapper = new QueryWrapper<>();
            orderInfoWrapper.eq("schedule_id",schedule.getId());
            orderInfoWrapper.eq("order_status",2);//2表示已支付
            List<OrderInfo> orderInfoList = orderInfoService.list(orderInfoWrapper);
            //根据订单列表查询出对应的病人，并放入到对应的list中
            for (OrderInfo orderInfo : orderInfoList) {
                QueryWrapper<Patient> patientWrapper = new QueryWrapper<>();
                patientWrapper.eq("card_no",orderInfo.getCardNo());
                Patient patient = baseMapper.selectOne(patientWrapper);
                //设置其他值
                Map<String,Object> params = new HashMap<>();
                if (!StringUtils.isEmpty(patientListR)){
                    for (Patient pat : patientListR) {
                        if (pat.getId()==patient.getId()){
                            params.put("overtime",pat.getParams().get("overtime"));
                        }
                    }
                }

                if (!StringUtils.isEmpty(patientVisit)&&patient.getId()==patientVisit.getId()){
                    params.put("overtime",2);
                }

                if (!StringUtils.isEmpty(patientOvertimeList)){
                    for (Patient overtimePat : patientOvertimeList) {
                        if (overtimePat.getId()==patient.getId()){
                            params.put("overtime",1);
                        }
                    }
                }

                params.put("orderStatus",orderInfo.getOrderStatus());
                params.put("waitTime",schedule.getWorkTime());
                params.put("orderInfoId",orderInfo.getId());
                patient.setParams(params);
                patientList.add(patient);
            }
        }
        Collections.sort(patientList, new Comparator<Patient>() {
            @Override
            public int compare(Patient p1, Patient p2) {
                return (Integer) p2.getParams().get("waitTime")-(Integer) p1.getParams().get("waitTime");
            }
        });
        return patientList;
    }

    @Override
    public List<Patient> getFromRedis(Long docId) {
        List<Patient> list =(List<Patient>) redisCache.getCacheObject("doctor:"+docId);
        return list;
    }

    @Override
    public boolean overtimePatient(String orderInfoId,Long docId) {
        //根据orderInfoId找出订单
        OrderInfo orderInfo = orderInfoService.findById(orderInfoId);

        //根据orderInfo的cardNo查询出病人信息
        QueryWrapper<Patient> wrapper = new QueryWrapper<>();
        wrapper.eq("card_no",orderInfo.getCardNo());
        Patient patient = baseMapper.selectOne(wrapper);

        //设置patient的其他值
        Map<String,Object> params = new HashMap<>();
        params.put("orderInfoId",orderInfoId);
        patient.setParams(params);

        //先在待就诊队列里移除该病人的信息，再更新到redis中
        List<Patient> patientListR =(List<Patient>) redisCache.getCacheObject("doctor:"+docId);
        //定义flag标志是否移除成功
        boolean flag=false;
        for (Patient pat : patientListR) {
            if (pat.getId()==patient.getId()){
                patientListR.remove(pat);
                flag=true;
                break;
            }
        }

        if (!flag){//说明待就诊队列里面没有该病人信息
            return flag;
        }

        //根据docId找出redis中的过号队列
        List<Patient> patientOvertimeList =(List<Patient>) redisCache.getCacheObject("doctor:"+docId+":overtime");
        if (StringUtils.isEmpty(patientOvertimeList)){
            patientOvertimeList = new LinkedList<>();
            patientOvertimeList.add(patient);
        }else{
            //判断有无过号患者信息
            for (Patient overPat : patientOvertimeList) {
                if (overPat.getId()==patient.getId()){//说明患者已经被进行过号处理
                    return false;
                }
            }
            patientOvertimeList.add(patient);
        }

        //将两个列表存放到redis中
        redisCache.setCacheObject("doctor:"+docId+":overtime",patientOvertimeList);
        redisCache.setCacheObject("doctor:"+docId,patientListR);
        return true;
    }

    @Override
    public boolean visitPatient(Long type, String orderInfoId,Long docId) {
        Patient patR = (Patient) redisCache.getCacheObject("doctor:"+docId+":visit");

        if (!StringUtils.isEmpty(patR)){//说明上一个患者还没就诊完
            return false;
        }

        //根据orderInfoId找出订单
        OrderInfo orderInfo = orderInfoService.findById(orderInfoId);

        //根据orderInfo的cardNo查询出病人信息
        QueryWrapper<Patient> wrapper = new QueryWrapper<>();
        wrapper.eq("card_no",orderInfo.getCardNo());
        Patient patient = baseMapper.selectOne(wrapper);

        //设置patient的其他值
        Map<String,Object> params = new HashMap<>();
        params.put("orderInfoId",orderInfoId);
        patient.setParams(params);

        if (type==0){
            //先在待就诊队列里移除该病人的信息，再更新到redis中
            List<Patient> patientListR =(List<Patient>) redisCache.getCacheObject("doctor:"+docId);
            for (Patient pat : patientListR) {
                if (pat.getId()==patient.getId()){
                    patientListR.remove(pat);
                    break;
                }
            }
            redisCache.setCacheObject("doctor:"+docId,patientListR);
        }else{
            //根据docId找出redis中的过号队列，移除该病人的信息，再更新到redis中
            List<Patient> patientOvertimeList =(List<Patient>) redisCache.getCacheObject("doctor:"+docId+":overtime");
            for (Patient pat : patientOvertimeList) {
                if (pat.getId()==patient.getId()){
                    patientOvertimeList.remove(pat);
                    break;
                }
            }
            redisCache.setCacheObject("doctor:"+docId+":overtime",patientOvertimeList);
        }

        //往redis存储就诊的患者信息
        redisCache.setCacheObject("doctor:"+docId+":visit",patient);

        return true;
    }

    @Override
    public List<Patient> getMedicatedPatientList(Long userId) {
        List<String> prescriptionIdList = (List<String>) redisCache.getCacheObject("drugstore:"+userId+":wait");
        if (StringUtils.isEmpty(prescriptionIdList)||prescriptionIdList.size()==0){
            return null;
        }

        //根据处方编号列表查询出对应的处方
        QueryWrapper<Prescription> wrapper = new QueryWrapper<>();
        wrapper.in("id",prescriptionIdList);
        List<Prescription> prescriptionList = prescriptionService.list(wrapper);

        List<Patient> patientList = new ArrayList<>();
        //遍历prescriptionList，根据处方中的就诊卡号查询出病人信息
        for (Prescription prescription : prescriptionList) {
            QueryWrapper<Patient> patientWrapper = new QueryWrapper<>();
            patientWrapper.eq("card_no",prescription.getCardNo());
            Patient patient = baseMapper.selectOne(patientWrapper);

            //设置其他值
            Map<String,Object> params = new HashMap<>();
            params.put("prescriptionId",prescription.getId());
            patient.setParams(params);

            //添加到list集合中
            patientList.add(patient);
        }
        return patientList;
    }

    @Override
    public List<Patient> getWaitPatientList(Long userId) {
        List<String> prescriptionIdList = (List<String>) redisCache.getCacheObject("drugstore:"+userId+":finish");
        if (StringUtils.isEmpty(prescriptionIdList)||prescriptionIdList.size()==0){
            return null;
        }

        //根据处方编号列表查询出对应的处方
        QueryWrapper<Prescription> wrapper = new QueryWrapper<>();
        wrapper.in("id",prescriptionIdList);
        List<Prescription> prescriptionList = prescriptionService.list(wrapper);

        List<Patient> patientList = new ArrayList<>();
        //遍历prescriptionList，根据处方中的就诊卡号查询出病人信息
        for (Prescription prescription : prescriptionList) {
            QueryWrapper<Patient> patientWrapper = new QueryWrapper<>();
            patientWrapper.eq("card_no",prescription.getCardNo());
            Patient patient = baseMapper.selectOne(patientWrapper);

            //设置其他值
            Map<String,Object> params = new HashMap<>();
            params.put("prescriptionId",prescription.getId());
            patient.setParams(params);

            //添加到list集合中
            patientList.add(patient);
        }
        return patientList;
    }


}




